package cn.wolfcode.web.controller;

import cn.wolfcode.common.constants.CommonConstants;
import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.CommonCodeMsg;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.common.web.anno.RequireLogin;
import cn.wolfcode.domain.OrderInfo;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.mq.MQConstant;
import cn.wolfcode.mq.OrderMessage;
import cn.wolfcode.redis.CommonRedisKey;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.util.DateUtil;
import cn.wolfcode.util.UserUtil;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

/**
 * Created by lanxw
 */
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderInfoController {
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;
    @Autowired
    private IOrderInfoService orderInfoService;

    /**
     * 查看秒杀订单详情
     *
     * @param orderNo
     * @param request
     * @return
     */
    @RequestMapping("/find")
    public Result<OrderInfo> find(String orderNo, HttpServletRequest request) {
        //OrderInfo orderInfo = orderInfoService.find(orderNo);
        OrderInfo orderInfo = orderInfoService.findFromCache(orderNo);
        // 判断查询出来的订单是否是当前登录用户的
        String token = request.getHeader(CommonConstants.TOKEN_NAME); //"token"
        String phone = UserUtil.getUserPhone(redisTemplate,token);
        if (!phone.equals(orderInfo.getPhone())) {
            throw new BusinessException(CommonCodeMsg.ILLEGAL_OPERATION);
        }
        return Result.success(orderInfo);
    }

    /**
     * 点击抢购秒杀商品生成秒杀订单
     *
     * @param time
     * @param seckillId
     * @param request
     * @return
     */
    @RequestMapping("/doSeckill")
    @RequireLogin
    public Result<String> doSeckill(Integer time,Long seckillId,HttpServletRequest request) {
        // 缓存中获取指定的秒杀商品
        SeckillProductVo seckillProductVo = seckillProductService.findFromCache(time, seckillId);
        // 判断秒杀商品是否在秒杀时间段内
        /*boolean legalTime = DateUtil.isLegalTime(seckillProductVo.getStartDate(), time);
        if (!legalTime) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }*/
        // 每个用户只能买一次指定的秒杀商品，从缓存中获取手机号与订单的关系set数据来判断是否重复下单
        String token = request.getHeader(CommonConstants.TOKEN_NAME); //"token"

        //String phone = redisTemplate.opsForValue().get(CommonRedisKey.USER_TOKEN.getRealKey(token));
        String phone = UserUtil.getUserPhone(redisTemplate, token);
        // 指定商品的订单所有相关联手机号的key
        String orderSetKey = SeckillRedisKey.SECKILL_ORDER_SET.getRealKey(seckillId + "");
        // 判断该用户的手机号是否存在该set集合中，如果存在说明下过单了
        Boolean hasOrder = redisTemplate.opsForSet().isMember(orderSetKey, phone);
        if (hasOrder) {
            // 存在
            throw new BusinessException(SeckillCodeMsg.REPEAT_SECKILL);
        }
        // 库存不足
        // 存储库存数量的key
        // 通过redis的原子性递减控制请求人数
        String countHashKey = SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(time + "");
        // 缓存中预库存减一,remainCount是减一之后返回的库存数量，这里如果是高并发的话可以筛选掉很多请求量
        Long remainCount = redisTemplate.opsForHash().increment(countHashKey, seckillProductVo.getId() + "", -1);
        if (remainCount < 0) {
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }

        // ------------  原子性操作-----------
        // 对数据库的库存进行扣减的操作
        // 创建秒杀订单
        // ------------  原子性操作-----------
        /*String orderNo = orderInfoService.doSecKill(time,seckillId,phone);*/
        // 返回订单的订单号
        /*return Result.success(orderNo);*/
        // 消息内容
        OrderMessage msg = new OrderMessage(time, seckillId, token, phone);
        // 异步发送
        rocketMQTemplate.asyncSend(MQConstant.ORDER_PEDDING_TOPIC, msg, new SendCallback() {
            @Override
            public void onSuccess(SendResult sendResult) {
                System.out.println("消息发送到业务MQ成功");
            }

            @Override
            public void onException(Throwable throwable) {
                System.out.println("系统处理异常，请联系管理员");
            }
        });
        return Result.success("进入队列成功，等待消息结果");
    }
}
